﻿#ifndef YUTOPP_OAUTH_COMMON_AUTHENTICATOR_1_HPP
#define YUTOPP_OAUTH_COMMON_AUTHENTICATOR_1_HPP

#include "../../detail/base.hpp"
#include "basic_authenticator.hpp"

#include <vector>

#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/home/qi/char/char_class.hpp>

namespace webapp
{
	namespace oauth
	{
		//汎用認証クラス
		template<typename Protocol, typename Policy>
		class common_authenticator<
			Protocol,
			Policy,
			typename boost::enable_if<
				is_v1<typename Policy::auth_type>
			>::type
		>
			: public basic_authenticator<common_authenticator<Protocol, Policy>, Protocol, Policy>
		{
			typedef basic_authenticator<common_authenticator<Protocol, Policy>, Protocol, Policy>
				base_type;

			friend base_type;

			typedef typename Policy::request_token				request_token;
			typedef typename Policy::access_token				access_token;

		public:
			typedef typename base_type::auth_key_type			auth_key_type;
			typedef typename base_type::binary_type				binary_type;
			typedef typename base_type::optional_request_token	optional_request_token;
			typedef typename base_type::optional_access_token	optional_access_token;

			explicit common_authenticator( const auth_key_type& key )
				: base_type( key )
			{}

		private:
			optional_request_token
				parse_request_token( const binary_type& response ) const
			{
				namespace qi = boost::spirit::qi;

				std::vector<binary_type> v;

				binary_type::const_iterator begin = response.begin();
				binary_type::const_iterator end = response.end();

				const bool r = qi::phrase_parse( begin, end,
					qi::lit( "oauth_token" ) >> "="  >> +(qi::char_ - '&') >> '&'
					>> "oauth_token_secret" >> "=" >> +(qi::char_ - '&') >> '&'
					>> "oauth_callback_confirmed" >> "=" >> +qi::char_,
					boost::spirit::ascii::space,
					v
					);

				if ( r ) {
					return request_token( v.at( 0 ), v.at( 1 ) );
				} else {
					return boost::none;
				}
			}

			optional_access_token
				parse_access_token( const binary_type& response )
			{
				namespace qi = boost::spirit::qi;

				std::vector<binary_type> v;

				binary_type::const_iterator begin = response.begin();
				binary_type::const_iterator end = response.end();

				const bool r = qi::phrase_parse( begin, end,
					qi::lit( "oauth_token" ) >> "="  >> +(qi::char_ - '&') >> '&'
					>> "oauth_token_secret" >> "=" >> +(qi::char_ - '&'),
					boost::spirit::ascii::space,
					v
					);

				if ( r ) {
					set_token( v.at( 0 ), v.at( 1 ) );
					return access_token();
				} else {
					return boost::none;
				}
			}
		};
	} // - oauth
} // - webapp

#endif /*YUTOPP_OAUTH_COMMON_AUTHENTICATOR_1_HPP*/
